# -*- coding: utf-8; -*-

"""Siocwave configuration management."""

import os
import os.path
import ConfigParser


RECENT_COUNT = 10
"""The number of entries to keep in the "recently loaded" menu."""


def guess_config_dir():
    """Return a guess at the appropriate location for the config dir."""
    if 'XDG_CONFIG_HOME' in os.environ:
        return os.path.join(os.environ['XDG_CONFIG_HOME'], 'siocwave')
    elif 'APPDATA' in os.environ:
        return os.path.join(os.environ['APPDATA'], 'Siocwave')
    else:
        return os.path.expanduser('~/.siocwave')

def guess_cache_dir():
    """Return a guess at the appropriate location for the cache dir."""
    if 'XDG_CACHE_HOME' in os.environ:
        return os.path.join(os.environ['XDG_CACHE_HOME'], 'siocwave')
    elif 'TEMP' in os.environ:
        return os.path.join(os.environ['TEMP'], 'Siocwave')
    else:
        return os.path.expanduser('~/.siocwave/cache')


class ConfigMgr(object):
    """Manages configuration of Siocwave.
    
    An instance of this class sits on top of the graph manager and tweaks its
    settings according to the user's preferences, specified in a config file
    and changeable via the GUI. It also provides access to a list of recently
    loaded URLs.
    """
    
    def __init__(self, graph_mgr, config_dir=None):
        """Create a configuration manager.
        
        Create a configuration manager that will set up the graph manager
        `graph_mgr`. If `conf_dir` is specified, it must be the `str` path to
        a filesystem directory where Siocwave configuration should be stored.
        """
        self.graph_mgr = graph_mgr
        if config_dir is None:
            self.config_dir = guess_config_dir()
        else:
            self.config_dir = config_dir
    
    def load(self):
        """Configure the application on startup.
        
        Set up the graph manager according to the user's stored preferences.
        If there are none, load defaults.
        """
        self.parser = ConfigParser.RawConfigParser()
        self.parser.read(os.path.join(self.config_dir, 'siocwave.ini'))
        
        # Cache location.
        try:
            self.set_cache(self.parser.get('cache', 'location'))
        except Exception:
            self.set_cache(None)
            
        # RDFS auto inference on/off.
        try:
            self.set_rdfs_auto_infer(
                self.parser.getboolean('inference', 'rdfs_auto_infer')
            )
        except Exception:
            self.set_rdfs_auto_infer(False)
        
        # URLs to preload.
        try:
            preload = self.parser.items('preload')
            self.set_preload([unicode(value) for name, value in preload])
        except Exception:
            self.set_preload([])
        
        # Recently loaded graphs.
        try:
            recent = self.parser.items('recent')
            recent.sort(key=lambda (n, v): n)
            self.recent = [unicode(value) for name, value in recent]\
                          [:RECENT_COUNT]
        except ConfigParser.NoSectionError:
            self.recent = []
    
    def set_cache(self, cache):
        """Set cache directory to `cache` (an `str` or None)."""
        if cache == '':
            cache = None
        self.graph_mgr.cache = cache
    
    def get_cache(self):
        """Get the current cache directory (an `str` or None)."""
        return self.graph_mgr.cache
    
    def set_rdfs_auto_infer(self, value):
        """Set the RDFS auto-inference option to `value` (True or False)."""
        self.graph_mgr.rdfs_auto_infer = value
    
    def get_rdfs_auto_infer(self):
        """Get the value of the RDFS auto-inference option (True or False)."""
        return self.graph_mgr.rdfs_auto_infer
    
    def set_preload(self, preload):
        """Set `preload` as the list of URLs to be preloaded."""
        self.graph_mgr.preload_list = preload
    
    def get_preload(self):
        """Get the current list of preloaded URLs."""
        return list(self.graph_mgr.preload_list)
    
    def add_recent(self, url):
        """Add `url` to the list of recently loaded graphs.
        
        If `url` is not yet in the list, add it, removing the oldest item
        if necessary (to keep the limit of recent items). If it is already in
        the list, move it to the top.
        """
        if url in self.recent:
            self.recent.pop(self.recent.index(url))
            self.recent.insert(0, url)
        else:
            self.recent.insert(0, url)
            if len(self.recent) > RECENT_COUNT:
                self.recent.pop(RECENT_COUNT)
        self.save()
    
    def save(self):
        """Save current configuration.
        
        Save current configuration to persistent storage. Return True if this
        succeeds, False otherwise.
        """
        if self.parser is None:
            self.parser = ConfigParser.RawConfigParser()
            self.parser.read(os.path.join(self.config_dir, 'siocwave.ini'))
        
        # Save cache.
        if not self.parser.has_section('cache'):
            self.parser.add_section('cache')
        cache = self.get_cache()
        if cache is None:
            cache = ''
        self.parser.set('cache', 'location', cache)
        
        # Save RDFS inference on/off.
        if not self.parser.has_section('inference'):
            self.parser.add_section('inference')
        if self.get_rdfs_auto_infer():
            self.parser.set('inference', 'rdfs_auto_infer', 'on')
        else:
            self.parser.set('inference', 'rdfs_auto_infer', 'off')
        
        # Save preload list.
        if self.parser.has_section('preload'):
            self.parser.remove_section('preload')    # Clear the list
        self.parser.add_section('preload')
        for i, url in enumerate(self.get_preload()):
            self.parser.set('preload', str(i), str(url))
        
        # Save recents.
        if self.parser.has_section('recent'):
            self.parser.remove_section('recent')    # Clear the list
        self.parser.add_section('recent')
        for i, url in enumerate(self.recent):
            self.parser.set('recent', str(i), str(url))
        
        try:
            if not os.path.exists(self.config_dir):
                os.mkdir(self.config_dir)
            conffile = open(os.path.join(self.config_dir, 'siocwave.ini'), 'w')
            self.parser.write(conffile)
            conffile.close()
            return True
        except Exception:
            return False
